{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.model_selection import StratifiedKFold\n",
    "import lightgbm as lgb\n",
    "import numpy as np\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "from sklearn import metrics\n",
    "from sklearn.metrics import accuracy_score\n",
    "import time\n",
    "from pyspark.sql import SparkSession\n",
    "from concurrent.futures import ThreadPoolExecutor\n",
    "from sklearn.ensemble import VotingClassifier\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.ensemble import BaggingClassifier\n",
    "from sklearn.neural_network import MLPClassifier\n",
    "from sklearn.svm import SVC\n",
    "import xgboost as xgb\n",
    "import warnings\n",
    "import pickle\n",
    "from boruta import BorutaPy\n",
    "import matplotlib.pyplot as plt\n",
    "from catboost import CatBoostClassifier\n",
    "from sklearn.ensemble import AdaBoostClassifier\n",
    "from sklearn.ensemble import GradientBoostingClassifier\n",
    "from sklearn.model_selection import RandomizedSearchCV\n",
    "from skdist.distribute.search import DistGridSearchCV\n",
    "from sklearn.ensemble import BaggingClassifier,RandomForestClassifier,ExtraTreesClassifier,GradientBoostingClassifier\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# all_data = pd.read_csv('data_demo4.csv')\n",
    "# train_all_data=all_data[:28000]\n",
    "# test_all_data=all_data[28000:]\n",
    "# train_all_data[\"type\"] = train_all_data[\"type\"].map({'围网':0,'刺网':1,'拖网':2})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_all_data = pd.read_hdf('data/train_transform.h5')\n",
    "test_all_data = pd.read_hdf('data/test_transform.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train = train_all_data.drop(['type'], axis=1)\n",
    "y_train = train_all_data[\"type\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## LGBMClassifier plot_importance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train():\n",
    "    voting_clf = lgb.LGBMClassifier(learning_rate=0.22149993885702932,\n",
    "                                         min_child_samples=7, #它的值取决于训练数据的样本个树和num_leaves. 将其设置的较大可以避免生成一个过深的树, 但有可能导致欠拟合。\n",
    "                                         max_depth=7, #设置树深度，深度越大可能过拟合\n",
    "                                         lambda_l1=2,boosting=\"gbdt\",objective=\"multiclass\",\n",
    "                                         n_estimators=2400,metric='multi_error',num_class=3,\n",
    "                                         feature_fraction=0.75,bagging_fraction=0.85,seed=99,\n",
    "                                         num_threads=20,verbose=-1,n_jobs=-1,device=\"cpu\")\n",
    "    voting_clf.fit(X_train,y_train)\n",
    "    return voting_clf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6.7006237506866455\n"
     ]
    }
   ],
   "source": [
    "start = time.time()\n",
    "\n",
    "with ThreadPoolExecutor(max_workers=10) as t: \n",
    "    f1 = t.submit(train)\n",
    "    model = f1.result()\n",
    "\n",
    "end = time.time()\n",
    "print(str(end-start))  #841.635686"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "lgb.plot_importance(model, max_num_features=30)\n",
    "plt.title(\"Featurertances\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "booster = model.booster_\n",
    "importance = booster.feature_importance(importance_type='split')\n",
    "feature_name = booster.feature_name()\n",
    "feature_importance = pd.DataFrame({'feature_name':feature_name,'importance':importance} )\n",
    "feature_importance.sort_values(\"importance\",\n",
    "                               inplace=True, #是否用排序后的数据集替换原来的数据，默认为False，即不替换\n",
    "                               ascending=False) #是否升序，false是倒序\n",
    "feature_importance.to_csv('data/feature_importance.csv',index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "feature_importance_list = feature_importance.loc[feature_importance[\"importance\"] != 0][\"feature_name\"].tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train=X_train[feature_importance_list]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(7000, 321)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Index(['y_max_x_min', 'x_max_y_min', 'slope', 'skew_x', 'skew_y',\n",
       "       'mean_minute', 'skew_minute', 'mode_x', 'mode_x_y_', 'std_minute',\n",
       "       ...\n",
       "       'quantile0.25_day', 'nunique_weekday', 'start-end_hour',\n",
       "       'median_weekday', 'mode_x_y_d_', 'mode_x_y_v_d_', 'median_day',\n",
       "       'mode_y_d_', 'quantile0.25_y_v_d_', 'median_hour'],\n",
       "      dtype='object', length=321)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(X_train.shape)\n",
    "X_train.columns"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## boruta "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "#y_train.ravel()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# define random forest classifier, with utilising all cores and\n",
    "# sampling in proportion to y labels\n",
    "rf = RandomForestClassifier(n_jobs=-1, class_weight='balanced', max_depth=5)\n",
    "\n",
    "# define Boruta feature selection method\n",
    "feat_selector = BorutaPy(rf, n_estimators='auto', verbose=2, random_state=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: \t1 / 100\n",
      "Confirmed: \t0\n",
      "Tentative: \t321\n",
      "Rejected: \t0\n",
      "Iteration: \t2 / 100\n",
      "Confirmed: \t0\n",
      "Tentative: \t321\n",
      "Rejected: \t0\n",
      "Iteration: \t3 / 100\n",
      "Confirmed: \t0\n",
      "Tentative: \t321\n",
      "Rejected: \t0\n",
      "Iteration: \t4 / 100\n",
      "Confirmed: \t0\n",
      "Tentative: \t321\n",
      "Rejected: \t0\n",
      "Iteration: \t5 / 100\n",
      "Confirmed: \t0\n",
      "Tentative: \t321\n",
      "Rejected: \t0\n",
      "Iteration: \t6 / 100\n",
      "Confirmed: \t0\n",
      "Tentative: \t321\n",
      "Rejected: \t0\n",
      "Iteration: \t7 / 100\n",
      "Confirmed: \t0\n",
      "Tentative: \t321\n",
      "Rejected: \t0\n",
      "Iteration: \t8 / 100\n",
      "Confirmed: \t197\n",
      "Tentative: \t61\n",
      "Rejected: \t63\n",
      "Iteration: \t9 / 100\n",
      "Confirmed: \t197\n",
      "Tentative: \t61\n",
      "Rejected: \t63\n",
      "Iteration: \t10 / 100\n",
      "Confirmed: \t197\n",
      "Tentative: \t61\n",
      "Rejected: \t63\n",
      "Iteration: \t11 / 100\n",
      "Confirmed: \t197\n",
      "Tentative: \t61\n",
      "Rejected: \t63\n",
      "Iteration: \t12 / 100\n",
      "Confirmed: \t201\n",
      "Tentative: \t57\n",
      "Rejected: \t63\n",
      "Iteration: \t13 / 100\n",
      "Confirmed: \t201\n",
      "Tentative: \t57\n",
      "Rejected: \t63\n",
      "Iteration: \t14 / 100\n",
      "Confirmed: \t201\n",
      "Tentative: \t57\n",
      "Rejected: \t63\n",
      "Iteration: \t15 / 100\n",
      "Confirmed: \t201\n",
      "Tentative: \t57\n",
      "Rejected: \t63\n",
      "Iteration: \t16 / 100\n",
      "Confirmed: \t201\n",
      "Tentative: \t55\n",
      "Rejected: \t65\n",
      "Iteration: \t17 / 100\n",
      "Confirmed: \t201\n",
      "Tentative: \t55\n",
      "Rejected: \t65\n",
      "Iteration: \t18 / 100\n",
      "Confirmed: \t201\n",
      "Tentative: \t55\n",
      "Rejected: \t65\n",
      "Iteration: \t19 / 100\n",
      "Confirmed: \t203\n",
      "Tentative: \t51\n",
      "Rejected: \t67\n",
      "Iteration: \t20 / 100\n",
      "Confirmed: \t203\n",
      "Tentative: \t51\n",
      "Rejected: \t67\n",
      "Iteration: \t21 / 100\n",
      "Confirmed: \t203\n",
      "Tentative: \t51\n",
      "Rejected: \t67\n",
      "Iteration: \t22 / 100\n",
      "Confirmed: \t204\n",
      "Tentative: \t50\n",
      "Rejected: \t67\n",
      "Iteration: \t23 / 100\n",
      "Confirmed: \t204\n",
      "Tentative: \t48\n",
      "Rejected: \t69\n",
      "Iteration: \t24 / 100\n",
      "Confirmed: \t204\n",
      "Tentative: \t48\n",
      "Rejected: \t69\n",
      "Iteration: \t25 / 100\n",
      "Confirmed: \t204\n",
      "Tentative: \t48\n",
      "Rejected: \t69\n",
      "Iteration: \t26 / 100\n",
      "Confirmed: \t206\n",
      "Tentative: \t46\n",
      "Rejected: \t69\n",
      "Iteration: \t27 / 100\n",
      "Confirmed: \t206\n",
      "Tentative: \t46\n",
      "Rejected: \t69\n",
      "Iteration: \t28 / 100\n",
      "Confirmed: \t206\n",
      "Tentative: \t46\n",
      "Rejected: \t69\n",
      "Iteration: \t29 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t45\n",
      "Rejected: \t69\n",
      "Iteration: \t30 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t45\n",
      "Rejected: \t69\n",
      "Iteration: \t31 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t45\n",
      "Rejected: \t69\n",
      "Iteration: \t32 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t33 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t34 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t35 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t36 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t37 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t38 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t39 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t40 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t41 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t43\n",
      "Rejected: \t71\n",
      "Iteration: \t42 / 100\n",
      "Confirmed: \t207\n",
      "Tentative: \t42\n",
      "Rejected: \t72\n",
      "Iteration: \t43 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t39\n",
      "Rejected: \t72\n",
      "Iteration: \t44 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t39\n",
      "Rejected: \t72\n",
      "Iteration: \t45 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t39\n",
      "Rejected: \t72\n",
      "Iteration: \t46 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t39\n",
      "Rejected: \t72\n",
      "Iteration: \t47 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t38\n",
      "Rejected: \t73\n",
      "Iteration: \t48 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t38\n",
      "Rejected: \t73\n",
      "Iteration: \t49 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t38\n",
      "Rejected: \t73\n",
      "Iteration: \t50 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t35\n",
      "Rejected: \t76\n",
      "Iteration: \t51 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t35\n",
      "Rejected: \t76\n",
      "Iteration: \t52 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t35\n",
      "Rejected: \t76\n",
      "Iteration: \t53 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t35\n",
      "Rejected: \t76\n",
      "Iteration: \t54 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t35\n",
      "Rejected: \t76\n",
      "Iteration: \t55 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t35\n",
      "Rejected: \t76\n",
      "Iteration: \t56 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t35\n",
      "Rejected: \t76\n",
      "Iteration: \t57 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t35\n",
      "Rejected: \t76\n",
      "Iteration: \t58 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t34\n",
      "Rejected: \t77\n",
      "Iteration: \t59 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t34\n",
      "Rejected: \t77\n",
      "Iteration: \t60 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t34\n",
      "Rejected: \t77\n",
      "Iteration: \t61 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t34\n",
      "Rejected: \t77\n",
      "Iteration: \t62 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t34\n",
      "Rejected: \t77\n",
      "Iteration: \t63 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t34\n",
      "Rejected: \t77\n",
      "Iteration: \t64 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t34\n",
      "Rejected: \t77\n",
      "Iteration: \t65 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t34\n",
      "Rejected: \t77\n",
      "Iteration: \t66 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t32\n",
      "Rejected: \t79\n",
      "Iteration: \t67 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t32\n",
      "Rejected: \t79\n",
      "Iteration: \t68 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t32\n",
      "Rejected: \t79\n",
      "Iteration: \t69 / 100\n",
      "Confirmed: \t210\n",
      "Tentative: \t32\n",
      "Rejected: \t79\n",
      "Iteration: \t70 / 100\n",
      "Confirmed: \t211\n",
      "Tentative: \t31\n",
      "Rejected: \t79\n",
      "Iteration: \t71 / 100\n",
      "Confirmed: \t211\n",
      "Tentative: \t31\n",
      "Rejected: \t79\n",
      "Iteration: \t72 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t73 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t74 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t75 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t76 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t77 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t78 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t79 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t80 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t81 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t82 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t83 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t84 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t85 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t86 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t87 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t88 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t89 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t90 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t91 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t92 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t93 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t94 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t95 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t96 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t97 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t98 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "Iteration: \t99 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t29\n",
      "Rejected: \t79\n",
      "\n",
      "\n",
      "BorutaPy finished running.\n",
      "\n",
      "Iteration: \t100 / 100\n",
      "Confirmed: \t213\n",
      "Tentative: \t7\n",
      "Rejected: \t79\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "BorutaPy(alpha=0.05,\n",
       "         estimator=RandomForestClassifier(bootstrap=True, ccp_alpha=0.0,\n",
       "                                          class_weight='balanced',\n",
       "                                          criterion='gini', max_depth=5,\n",
       "                                          max_features='auto',\n",
       "                                          max_leaf_nodes=None, max_samples=None,\n",
       "                                          min_impurity_decrease=0.0,\n",
       "                                          min_impurity_split=None,\n",
       "                                          min_samples_leaf=1,\n",
       "                                          min_samples_split=2,\n",
       "                                          min_weight_fraction_leaf=0.0,\n",
       "                                          n_estimators=440, n_jobs=-1,\n",
       "                                          oob_score=False,\n",
       "                                          random_state=RandomState(MT19937) at 0x7F52884F96B0,\n",
       "                                          verbose=0, warm_start=False),\n",
       "         max_iter=100, n_estimators='auto', perc=100,\n",
       "         random_state=RandomState(MT19937) at 0x7F52884F96B0, two_step=True,\n",
       "         verbose=2)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# find all relevant features - 5 features should be selected\n",
    "feat_selector.fit(X_train.values, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'feat_selector' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-1-278cded10c1c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# check selected features - first 5 features are selected\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mfeat_selector\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msupport_\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'feat_selector' is not defined"
     ]
    }
   ],
   "source": [
    "# check selected features - first 5 features are selected\n",
    "feat_selector.support_.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  1,   1,   1,   1,   1,   1,  54,   1,   1,  36,  29,   1,   1,\n",
       "         1,   1,   1,   1,   1,  70,  70,  10,  62,   1,  64,  46,   1,\n",
       "        37,  94,   1,  15,   1,   1,   1,   1,  82,   1,   1,   1,   1,\n",
       "        40,   1,   2,   1,   1,   2,   1,   1,  66,  49,   1,   1,   1,\n",
       "        33,   1,   1,   2,   1,  27,   1,  29,   1,   1,   1,   1,   1,\n",
       "         1,   1,   5,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,\n",
       "         1,  70,   1,   1,  10,   1,   1,   1,  34,   1,   1,   1,   1,\n",
       "         1,  80,   1,   1,   1,   1,   1,   1,  73,   1,  42,  34,   1,\n",
       "         1,   1,   1,   1,  17,   1,   1,  10,   1,   1,   1,   1,   1,\n",
       "         1,   1,  73,   1,   1,   1,   1,   1,  10,   1,   1,   1,  56,\n",
       "        60,   1,   1,   1,   1,  87,   1,   1,   1,   1,   1,   1,   1,\n",
       "         1,  24,  84,   1,   5,   1,   1,  68,  75,   1,   1,   1,   1,\n",
       "        96,   1,   1,   1,   1,   1,   1,   1,  82,   1,  41,  31,   1,\n",
       "         1,  58,   1,   1,   1,   1,   1,  89,   1,   1,  31,   1,   1,\n",
       "         1,   1,  20,   1,   1,   1,   1,  55,   1,   1,   1,   1,  10,\n",
       "         1,   1,   2,   1,  15,   1,   1,   1,   1,   1,   1,   2,   1,\n",
       "         1,   1,   2,   1,   3,   1,   1,  20,   1,  64,   1,   1,  60,\n",
       "         1,   1,   1,   1,   1, 102,   1,   1,  44,   1,   1,   1,   1,\n",
       "         1,   1,  27,  99,   1,   1,   1,   1,   1,  79,  86,  63,   1,\n",
       "         1,  84,  66,   1,   1,   1,   1,   1,   1,   1,  90,  39,  17,\n",
       "         1,  38,   1, 100,   1,   1,  92,  20,   1,   1,   1,   1,   1,\n",
       "        77, 100,   1,  80,   1,   1,   1,   1,  53,   1,   1,   1,  70,\n",
       "        75,   1,   1,  27,   1,   1,   1,   1,  51,  50,  10,  10,  23,\n",
       "        20,  94,  90,   1,  47,   5,  52,   2,  25,  77,  48,   1,  43,\n",
       "       103,  57,  88,  93,  98,  44,  97,  15,  60])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# check ranking of features\n",
    "feat_selector.ranking_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# call transform() on X to filter it down to selected features\n",
    "# X_filtered = feat_selector.transform(X_train.values)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(\"data/feat_selector.pkl\", 'wb') as fo:     # 将数据写入pkl文件\n",
    "    pickle.dump(feat_selector, fo)\n",
    "    \n",
    "# with open(\"dict_data.pkl\", 'rb') as fo:     # 读取pkl文件数据\n",
    "#     dict_data = pickle.load(fo, encoding='bytes')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
